package com.tanhua.server.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.tanhua.server.utils.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 作用：在进入Controller之前进行做缓存的命中，如果命中就返回数据，不再执行Controller中的逻辑
 * 如果没有命中，就放行，正常执行Controller中的逻辑
 * 条件：一般针对GET请求处理，被标记了@Cache注解的方法
 */
@Component
public class RedisCacheInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    //缓存的总开关
    @Value("${tanhua.cache.enable}")
    private Boolean cacheEnable;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {

        if (!cacheEnable) {
            return true;
        }

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //判断是否为GET请求
        if (!handlerMethod.hasMethodAnnotation(GetMapping.class)) {
            return true;
        }

        //判断是否包含@Cache注解
        if (!handlerMethod.hasMethodAnnotation(Cache.class)) {
            return true;
        }

        //进行缓存命中
        String redisKey = this.createRedisKey(request);
        String cacheData = this.redisTemplate.opsForValue().get(redisKey);
        if (StrUtil.isEmpty(cacheData)) {
            //缓存未命中
            return true;
        }

        //响应数据
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(cacheData);

        //拦截，不再执行Controller中的方法
        return false;
    }

    public static String createRedisKey(HttpServletRequest request) {
        //请求路径
        String url = request.getRequestURI();
        //请求参数
        String param = JSONUtil.toJsonStr(request.getParameterMap());
        //请求头
        String token = request.getHeader("Authorization");

        return "TANHUA_CACHE_" + SecureUtil.md5(url + param + token);
    }
}
